-- UIItemCompound
-- Created by chendh Jul/07/2015
-- 物品合成界面

require "game/ui/form/main/UISubAreaList"
require "game/ui/form/item/UIMaterialCompound"
require "game/ui/form/item/UIGainItemPath"
require "game/ui/form/item/UIBuyMaterial"

-- UIItemCompound继承自Layer
UIItemCompound = class("UIItemCompound", function()
    return cc.Layer:create();
end);

function UIItemCompound.create(heroId, classId, tab, feedId)
    return UIItemCompound.new(heroId, classId, tab, feedId);
end

-- 物品类型定义
local TYPE_FOOD     = "food";
local TYPE_MATERIAL = "material";
local TYPE_EQUIP    = "equip";
local TYPE_PROPERTY = "property";
local TYPE_AIRSHIP_DEVICE = "device";
local TYPE_DEVICE_MATERIAL = "device_material";
local TYPE_AWAKE_PEARL = "pearl";

-- 内部函数声明
local resize;

-- 构造函数
function UIItemCompound:ctor(heroId, classId, tab, feedId)
    -- 初始化
    self:setName("UIItemCompound");
    local node = cc.CSLoader:createNode("layout/item/ItemCompound.csb");
    self:addChild(node);
    self.node = node;
    self.heroId = heroId;
    self.classId = classId;
    self.feedId = feedId;
    self.materialList = {};

    if not tab then
        tab = {};
    end

    table.insert(tab, {heroId, classId});
    self.tab = tab;

    if DungeonM.isInDungeon() and not DungeonM.isPause() then
        -- 如果在迷宫中，需要提高层级
        self:setLocalZOrder(UIMgr.TOP_MENU_ZORDER + 1);
    end

    -- 注册事件处理回调函数
    self:registerEventCallback();

    -- 初始化窗口
    self:initForm();

    -- 注册点击事件
    self:registerTouchEvent();

    -- 重绘
    self:redraw();

    -- 适配
    resize(node);
end

-- 适配
function resize(node)
    -- bg居中显示并充满整个屏幕
    AlignM.fitToScreen(node, "bg");

    -- CT居中并缩放至合适大小
    AlignM.alignToCenter(node, "CT");

    -- BT置于底部并缩放至合适大小
    AlignM.alignToBottomCenter(node, "BT");
end

-- 初始化窗口
function UIItemCompound:initForm()
    -- 根据要合成的物品类型，选择界面的类型
    if ItemM.query(self.classId, "type") == ITEM_TYPE_FOOD then
        self.type = TYPE_FOOD;
    elseif ItemM.query(self.classId, "type") == ITEM_TYPE_MATERIAL then
        self.type = TYPE_MATERIAL;
    elseif ItemM.query(self.classId, "type") == ITEM_TYPE_PROPERTY then
        self.type = TYPE_PROPERTY;
    elseif EquipM.isEquipment(self.classId) then
        self.type = TYPE_EQUIP;
    elseif ItemM.query(self.classId, "type") == ITEM_TYPE_AIRSHIP_DEVICE then
        self.type = TYPE_AIRSHIP_DEVICE;
    elseif ItemM.query(self.classId, "type") == ITEM_TYPE_DEVICE_MATERIAL then
        self.type = TYPE_DEVICE_MATERIAL;
    elseif ItemM.query(self.classId, "group") == 38 then
        self.type = TYPE_AWAKE_PEARL;
    else
        assert(false, string.format("暂不支持物品(%d)的合成：", self.classId));
    end

    -- 收集合成的消耗
    local compoundCost = {};

    local rule = CompoundM.getCompoundRule(self.classId);
    if type(rule) ~= "string" or string.len(rule) <= 0 then
        trace("UIItemCompound", "获取不到合成规则。");
        return;
    end

    -- 获取合成配置(compound_rule.csv表中)
    -- product  ：产物
    -- material ：材料
    local compoundInfo = CompoundM.query(rule);
    if not compoundInfo then
        error(string.format("获取不到物品(%d)的合成信息", self.classId));
        return;
    end

    -- 所需的材料
    local needmaterial = table.deepcopy(compoundInfo.material);
    needmaterial = FormulaM.invoke("CALC_COMPOUND_MATERIAL", ME.user, needmaterial, compoundInfo.type);

    -- 对key重新排序
    local keyList = table.keys(needmaterial);
    table.sort(keyList, function(a, b) return a < b; end);

    -- 取出遗迹碎片放在表的末尾
    for i = 1, #keyList do
        if keyList[i] == 10000 then
            table.remove(keyList, i);
            table.insert(keyList, 10000);
            break;
        end
    end

    for index = 1, #keyList do
        local id = keyList[index];
        local requireNum = needmaterial[id];
        local info = ItemM.query(id);
        local ownNum = ItemM.getAmount(ME.user, id);

        table.insert(compoundCost, {id, requireNum});
    end

    -- 属性消耗
    local costInfo = CompoundM.calcCost(rule);
    local attribCost = "";

    for _, arr in pairs(costInfo) do
        if arr[1] == 2 then
            table.insert(compoundCost, {arr[2], arr[3]});
        end
    end

    -- 消耗收集完毕，记录下来
    self.compoundCost = compoundCost;

    -- 合成材料显示区域
    local costNum = #self.compoundCost;
    local twoItemsNode = findChildByName(self.node, "CT/two_items");
    local threeItemsNode = findChildByName(self.node, "CT/three_items");
    local fourItemsNode = findChildByName(self.node, "CT/four_items");

    -- 根据合成材料的种类数显示不同的材料节点 目前支持2-4种
    if costNum == 2 then
        -- 消耗2种东西来合成
        twoItemsNode:setVisible(true);
        threeItemsNode:setVisible(false);
        fourItemsNode:setVisible(false);

        self.itemsNode = twoItemsNode;
    elseif costNum == 3 then
        -- 消耗3种东西来合成
        twoItemsNode:setVisible(false);
        threeItemsNode:setVisible(true);
        fourItemsNode:setVisible(false);

        self.itemsNode = threeItemsNode;
    elseif costNum == 4 then
        -- 消耗4种东西来合成
        twoItemsNode:setVisible(false);
        threeItemsNode:setVisible(false);
        fourItemsNode:setVisible(true);

        self.itemsNode = fourItemsNode;
    else
        assert(string.format("compound items num = %d.", costNum));
    end

    local itemList = {};
    for i = 1, costNum do
        local itemNode = findChildByName(self.itemsNode, "item" .. i);
        table.insert(itemList, itemNode);
    end
    self.itemList = itemList;
end

-- 重绘
function UIItemCompound:redraw()
    -- 重绘物品及描述
    self:redrawItemAndDesc();

    -- 绘制公共模板背景
    self:redrawTemplate();

    -- 重绘按钮
    self:redrawButtons();

    -- 重绘标签页
    self:redrawTabs();
end

-- 绘制标签页
function UIItemCompound:redrawTabs()
    local tabNode = findChildByName(self.node, "CT/tabs");
    local tabNum = #self.tab;

    -- 先移除旧的标签
    tabNode.rows = {};
    tabNode:removeAllChildren();

    -- 根据tab数据，生成新标签
    local widget = replaceNodeWithWidget(cc.CSLoader:createNode("layout/tab/tab.csb"));

    for i = 1, tabNum do
        local child = widget:clone();
        child:setName("tab" .. i);
        child.index = i;

        self:registerTabTouchEvent(child);

        -- 计算单元格坐标
        -- 这个坐标将是单元格的描点所在
        local x = (i - 1) * 68 - 210;
        local y = -34;

        child:setPositionX(x);
        child:setPositionY(y);

        local tabLight = findChildByName(child, "light");
        local tabImage = findChildByName(child, "tab");
        tabLight:setScaleX(0.7);
        tabImage:setScaleX(0.7);

        if i == tabNum then
            tabLight:setVisible(true);
        else
            tabLight:setVisible(false);
        end

        local tabText = findChildByName(child, "text");
        local tabIcon = findChildByName(child, "icon");

        tabText:setVisible(false);
        if self.tab[i] == "carving" then
            tabIcon:loadTexture(getAwakeIconPath("carving"));
        else
            tabIcon:loadTexture(getItemIconPath(ItemM.query(self.tab[i][2], "icon")));
        end
        tabIcon:setScale(0.5);

        tabNode:addChild(child)
        table.insert(tabNode.rows, child)
    end
end

-- 绘制公共模板背景
function UIItemCompound:redrawTemplate()
    -- 更换公共模板上方2侧的图片
    local bgType1 = findChildByName(self.node, "CT/template/bg_type");
    local bgType2 = findChildByName(self.node, "CT/template/bg_type2");

    local itemGroup = ItemM.query(self.classId, "group");
    if itemGroup == 19 or itemGroup == 20 then
        -- 是食物或者食材
        bgType1:loadTexture(getTitleBgIconPath("food"));
        bgType2:loadTexture(getTitleBgIconPath("food"));
    else
        bgType1:loadTexture(getTitleBgIconPath("upgrade"));
        bgType2:loadTexture(getTitleBgIconPath("upgrade"));
    end

    -- 绘制标题
    local titleLabel = findChildByName(self.node, "CT/template/title");
    local subHeadLabel = findChildByName(self.node, "CT/template/subhead");

    -- 先停止滚动
    if self.scrollingData and self.scrollingData.classId ~= self.classId then
        stopScrolling(subHeadLabel);
    end

    TextStyleM.setTitleStyle(titleLabel);
    titleLabel:setString(ItemM.query(self.classId, "name"));

    TextStyleM.setSubheadStyle(subHeadLabel);
    if self.type == TYPE_FOOD then
        subHeadLabel:setString(getLocStr("food_compounded_title"));
    elseif self.type == TYPE_MATERIAL or
        self.type == TYPE_DEVICE_MATERIAL or
        self.type == TYPE_AWAKE_PEARL then

        local curAmount = ItemM.getAmount(ME.user, self.classId);
        local scrollingData = self.scrollingData;

        -- 没有滚动过
        if not scrollingData or scrollingData.classId ~= self.classId then
            subHeadLabel:setString(string.format(getLocStr("own_num"), ItemM.getAmount(ME.user, self.classId)));

            self.scrollingData = {
                ["lastAmount"] = curAmount,
                ["classId"]    = self.classId,
            };
        else
            -- 滚动
            numScrolling(subHeadLabel, getLocStr("own_num"), scrollingData.lastAmount, curAmount, 30);

            scrollingData.lastAmount = curAmount;
        end
    elseif self.type == TYPE_EQUIP then
        subHeadLabel:setString(getLocStr("equip_compound"));
    elseif self.type == TYPE_AIRSHIP_DEVICE then
        subHeadLabel:setString(getLocStr("title_device_remould"));
    else
        subHeadLabel:setString(getLocStr("item_compund_title"));
    end
end

-- 重绘食物信息
function UIItemCompound:redrawItemAndDesc()
    local item = findChildByName(self.node, "CT/item");

    local buyMaterialImg = findChildByName(self.node, "CT/buy_material");
    buyMaterialImg:setVisible(false);

    -- 物品图标
    local iconImg = findChildByName(item, "item_icon");
    iconImg:loadTexture(getItemIconPath(ItemM.query(self.classId, "icon")));

    -- 物品星级
    local starNode = findChildByName(item, "star_node");
    local rank = ItemM.query(self.classId, "rank");
    local layer = createStarLayer(rank, "images/ui/symbol/star_little.png", "center", -0.7);
    if layer then
        starNode:removeAllChildren();
        starNode:addChild(layer);
    end

    -- 物品的背景框
    local frameImage = findChildByName(item, "item_bg");
    frameImage:loadTexture(getFrameBgIconPath("rank", 1));

    -- 属性描述
    local propDescLabel = findChildByName(self.node, "CT/prop_desc");

    -- 如果是装置的话，直接取item表里的描述
    local propStr;
    if self.type == TYPE_AIRSHIP_DEVICE or self.type == TYPE_DEVICE_MATERIAL then
        propStr = ItemM.query(self.classId, "detail");
    elseif self.type == TYPE_AWAKE_PEARL then
        propStr = getLocStr("awake_pearl_compound_desc");

        if AwakeM.canSmeltPearl(self.heroId) ~= true then
            propStr = "[red]" .. propStr .. "[-]";
        end
    else
        local props = {};

        -- 获取附加的属性
        if self.type == TYPE_FOOD then
            props = PetM.getFoodProp(self.classId, self.feedId);
        elseif self.type == TYPE_EQUIP then
            props = EquipM.query(self.classId, "prop");
        end

        -- 将属性转化为描述拼接起来
        propStr = EquipM.getEquipPropDesc(props);

        -- "用于合成冈布奥料理（3阶）"
        if self.type == TYPE_MATERIAL then
            if ItemM.query(self.classId, "group") == 20 then
                propStr = string.format(getLocStr("material_food"), ItemM.query(self.classId, "rank") + 1);
            elseif ItemM.query(self.classId, "group") == 15 then
                propStr = string.format(getLocStr("material_weapon"), ItemM.query(self.classId, "rank") + 1);
            end
        else
            -- 如果配置了合成描述
            local rule = CompoundM.getCompoundRule(self.classId);
            local desc = CompoundM.getCompoundDesc(rule);
            if type(desc) == "string" and desc ~= "" then
                propStr = desc;
            end
        end
    end

    TextStyleM.setTextStyle(propDescLabel, TextStyleM.TEXT_SIZE_SMALL, TextStyleM.TEXT_COLOR_BLUE);
    --propDescLabel:setString(propStr);
    propDescLabel = applyString(propDescLabel, propStr);

    self.materialList = {};

    -- 合成消耗描述
    for i = 1, #self.compoundCost do
        local item = self.itemList[i];
        local itemBg = findChildByName(item, "item_bg");
        local itemIcon = findChildByName(item, "item_icon");
        local itemNum = findChildByName(item, "item_num");
        local classId = self.compoundCost[i][1];
        local requireNum = self.compoundCost[i][2];

        item.index = i;

        if type(classId) == "string" then
            -- 属性消耗
            itemBg:setVisible(false);
            itemIcon:loadTexture("images/ui/compound/money.png");
            itemIcon:setScale(1);
            TextStyleM.setTextStyle(itemNum, TextStyleM.TEXT_SIZE_TINY, TextStyleM.TEXT_COLOR_BEIGE, true, -3);

            local ownNum = ME.user.dbase:query(classId) or 0;
            if ownNum >= requireNum then
                applyString(itemNum, tostring(requireNum), -3);
            else
                applyString(itemNum, "[light_red]" .. tostring(requireNum) .. "[-]", -3);
            end
        else
            -- 物品消耗
            itemIcon:loadTexture(getItemIconPath(ItemM.query(classId, "icon")));
            itemIcon:setScale(0.8);
            TextStyleM.setTextStyle(itemNum, TextStyleM.TEXT_SIZE_TINY, TextStyleM.TEXT_COLOR_BEIGE, true, -3);
            local ownNum = ItemM.getAmount(ME.user, classId);

            -- 古遗迹碎片特殊处理
            local posY = itemBg:getPositionY();
            if classId == ITEM_ID_RELIC then
                itemBg:setVisible(false);
                itemIcon:setScale(1.1);
                itemIcon:setPositionY(posY + 1);
                if ownNum >= requireNum then
                    applyString(itemNum, tostring(requireNum), -3);
                else
                    applyString(itemNum, "[light_red]" .. tostring(requireNum) .. "[-]", -3);
                end
            else
                itemBg:setVisible(true);
                itemIcon:setPositionY(posY);
                if ownNum >= requireNum then
                    applyString(itemNum, tostring(ownNum) .. "/" .. tostring(requireNum), -3);
                    if ItemM.query(classId, "type") == ITEM_TYPE_MATERIAL then
                        itemIcon:setScale(0.7);
                    end
                else
                    applyString(itemNum, "[light_red]" .. tostring(ownNum) .. "[-]/" .. tostring(requireNum), -3);

                    buyMaterialImg:setVisible(true);

                    local initScale = 0.9;
                    if ItemM.query(classId, "type") == ITEM_TYPE_MATERIAL then
                        initScale = 0.7;
                    end
                    itemIcon:setScale(initScale);
                    playBubbleAnima(itemIcon, false, initScale);

                    -- 计算当前可用材料还差多少
                    local needNum = requireNum - ownNum;
                    local needMaterial = {["classId"] = classId, ["needNum"] = needNum};
                    table.insert(self.materialList, needMaterial);
                end
            end
        end

         -- 检查购买按钮是否需要呼吸
        local buyMaterialImg = findChildByName(self.node, "CT/buy_material");
        if buyMaterialImg:isVisible() then
            -- 合成按钮
            local cost = FormulaM.invoke("CALC_BUY_MATERIAL_COST", self.materialList)[1] or {};
            local activityId;
            if cost[1] == 1 then
                activityId = ActivityM.getActivityIdByItem(cost[2]);
                if activityId <= 0 or ActivityDungeonM.getCurrentActivityId() == activityId then
                    -- 不是活动物品/或者活动期间的活动物品
                    buyMaterialImg:loadTexture(getItemIconPath(ItemM.query(cost[2], "icon")));
                end
            end

            if self:isCanBuy(activityId) then
                playBubbleAnima(buyMaterialImg, false, 1);
            end
        end

        self:registerMaterialTouchEvent(item);
    end
end

-- 重绘数量信息
function UIItemCompound:redrawItemNum()
    -- 绘制标题
    local subHeadLabel = findChildByName(self.node, "CT/template/subhead");
    TextStyleM.setSubheadStyle(subHeadLabel);

    -- 先停止滚动
    if self.scrollingData and self.scrollingData.classId ~= self.classId then
        stopScrolling(subHeadLabel);
    end

    if self.type == TYPE_FOOD then
        subHeadLabel:setString(getLocStr("food_compounded_title"));
    elseif self.type == TYPE_MATERIAL or self.type == TYPE_DEVICE_MATERIAL then
        local curAmount = ItemM.getAmount(ME.user, self.classId);
        local scrollingData = self.scrollingData;

        -- 没有滚动过
        if not scrollingData or scrollingData.classId ~= self.classId then
            subHeadLabel:setString(string.format(getLocStr("own_num"), ItemM.getAmount(ME.user, self.classId)));

            self.scrollingData = {
                ["lastAmount"] = curAmount,
                ["classId"]    = self.classId,
            };
        else
            -- 滚动
            numScrolling(subHeadLabel, getLocStr("own_num"), scrollingData.lastAmount, curAmount, 30);

            scrollingData.lastAmount = curAmount;
        end
    elseif self.type == TYPE_EQUIP then
        subHeadLabel:setString(getLocStr("equip_compound"));
    elseif self.type == TYPE_AIRSHIP_DEVICE then
        subHeadLabel:setString(getLocStr("title_device_remould"));
    else
        subHeadLabel:setString(getLocStr("item_compund_title"));
    end

    -- 合成消耗描述
    for i = 1, #self.compoundCost do
        local item = self.itemList[i];

        local itemNum = findChildByName(item, "item_num");
        local classId = self.compoundCost[i][1];
        local requireNum = self.compoundCost[i][2];

        if type(classId) == "string" then
            -- 属性消耗
            local ownNum = ME.user.dbase:query(classId) or 0;
            if ownNum >= requireNum then
                applyString(itemNum, tostring(requireNum), -3);
            else
                applyString(itemNum, "[light_red]" .. tostring(requireNum) .. "[-]", -3);
            end
        else
            -- 物品消耗
            local ownNum = ItemM.getAmount(ME.user, classId);
            if ownNum >= requireNum then
                applyString(itemNum, tostring(ownNum) .. "/" .. tostring(requireNum), -3);
            else
                applyString(itemNum, "[light_red]" .. tostring(ownNum) .. "[-]/" .. tostring(requireNum), -3);
            end
        end
    end
end

-- 重绘按钮
function UIItemCompound:redrawButtons()
    -- 返回按钮
    local btnBack = findChildByName(self.node, "BT/btn_back");
    TextStyleM.setTextStyle(btnBack, TextStyleM.TEXT_SIZE_MIDDLE, TextStyleM.TEXT_COLOR_BROWN_YELLOW, true);
    btnBack:setTitleText(getLocStr("btn_text_back"));

    local rule = CompoundM.getCompoundRule(self.classId);

    -- 如果不是玩家自己打开界面，则隐藏返回按钮，强制要求玩家点击确定
    if CompoundM.query(rule, "remind_compound") == TRUE then
        btnBack:setVisible(false);
    else
        btnBack:setVisible(true);
    end

    -- 获取途径按钮
    local btnAchieve = findChildByName(self.node, "CT/btn_achieve");
    btnAchieve:setVisible(false);

    -- 合成按钮
    local gemImg = findChildByName(self.node, "CT/buy_material");

    -- 确定按钮
    local btnOk = findChildByName(self.node, "CT/btn_ok");
    TextStyleM.setTextStyle(btnOk, TextStyleM.TEXT_SIZE_MIDDLE, TextStyleM.TEXT_COLOR_BROWN_YELLOW, true);

    if self.type == TYPE_FOOD then
        -- 合成食物，显示"合成并喂食"
        btnOk:setTitleText(getLocStr("compound_and_feed"));
    elseif self.type == TYPE_EQUIP then
        -- 合成装备，显示'合成并佩戴'
        btnOk:setTitleText(getLocStr("compound_and_equip"));
    elseif self.type == TYPE_AIRSHIP_DEVICE then
        btnOk:setTitleText(getLocStr("remould"));
    elseif self.type == TYPE_DEVICE_MATERIAL then
        btnOk:setTitleText(getLocStr("compound_material"));
    elseif self.type == TYPE_AWAKE_PEARL then
        btnOk:setTitleText(getLocStr("btn_text_smelt_pearl"));
    else
        btnOk:setTitleText(getLocStr("btn_text_compound"));
    end

    -- 合成十个按钮
    local btnCompoundTen = findChildByName(self.node, "CT/btn_compound_ten");
    local maxNum = math.min(10, CompoundM.calcCanCompoundAmount(rule));
    btnCompoundTen.maxNum = maxNum;
    TextStyleM.setTextStyle(btnCompoundTen, TextStyleM.TEXT_SIZE_MIDDLE, TextStyleM.TEXT_COLOR_BROWN_YELLOW, true);
    btnCompoundTen:setTitleText(string.format(getLocStr("compound"), tostring(maxNum)));

    -- 合成按钮
    local btnCompound = findChildByName(self.node, "CT/btn_compound");
    TextStyleM.setTextStyle(btnCompound, TextStyleM.TEXT_SIZE_MIDDLE, TextStyleM.TEXT_COLOR_BROWN_YELLOW, true);
    btnCompound:setTitleText(string.format(getLocStr("compound"), tostring(1)));

    if self.type == TYPE_MATERIAL or self.type == TYPE_DEVICE_MATERIAL then
        if maxNum > 1 then
            btnCompound:setVisible(true);
            btnCompoundTen:setVisible(true)
            btnAchieve:setVisible(true);
            btnOk:setVisible(false);
            gemImg:setVisible(false);

        else
            btnCompound:setVisible(false);
            btnCompoundTen:setVisible(false)
            btnAchieve:setVisible(true);
            btnOk:setVisible(true);

            gemImg:setVisible(false);
        end
    else
        btnCompound:setVisible(false);
        btnCompoundTen:setVisible(false);
        btnAchieve:setVisible(false);
        btnOk:setVisible(true);
    end

    -- SLIMED-1533，喂食和飞艇改造，如果直接有成品可喂，则按钮直接可点
    local canFeed = false;

    if self.type == TYPE_AWAKE_PEARL then
        if CompoundM.canDoCompound(rule) and
            AwakeM.canSmeltPearl(self.heroId) == true then
            canFeed = true;
        end
    else
        if CompoundM.canDoCompound(rule) == true
            or ItemM.getAmount(ME.user, self.classId) > 0 then
            canFeed = true;
        end
    end

    if not canFeed then
        btnOk:setBright(false);
        btnOk:setTouchEnabled(false);

        btnCompound:setBright(false);
        btnCompound:setTouchEnabled(false);

        btnCompoundTen:setBright(false);
        btnCompoundTen:setTouchEnabled(false);
    else
        btnOk:setBright(true);
        btnOk:setTouchEnabled(true);

        btnCompound:setBright(true);
        btnCompound:setTouchEnabled(true);

        btnCompoundTen:setBright(true);
        btnCompoundTen:setTouchEnabled(true);
    end
end

-- 注册标签页点击回调
function UIItemCompound:registerTabTouchEvent(node)
    local tabImage = node:getChildByName("tab");
    local function onClick(sender, eventType)
        -- 点击时的回调
        if eventType == ccui.TouchEventType.ended then
            AudioM.playFx("button_click");

            local touchTab = self.tab[node.index];

            -- 如果剩下的是特殊的tab，那么直接退出界面了
            if type(touchTab) ~= "table" then
                UIMgr.getCurrentScene():removeFormByName("UIItemCompound");
                return;
            end

            self.heroId = touchTab[1];
            self.classId = touchTab[2];

            local tab = {}

            for i = 1, node.index do
                table.insert(tab, self.tab[i]);
            end
            self.tab = tab;

            -- 初始化窗口
            self:initForm();

            -- 重绘
            self:redraw();
        end
    end

    tabImage:addTouchEventListener(onClick);
end

-- 注册材料点击回调
function UIItemCompound:registerMaterialTouchEvent(node)
    local bgImage = node:getChildByName("item_bg");
    local itemImg = node:getChildByName("item_icon");
    local function onClick(sender, eventType)
        -- 点击时的回调
        if eventType == ccui.TouchEventType.ended then
            AudioM.playFx("button_click");

            local classId = self.compoundCost[node.index][1];
            local requireNum = self.compoundCost[node.index][2];

            local tab = self.tab;

            local rule = CompoundM.getCompoundRule(classId);

            if type(rule) == "string" and string.len(rule) > 0 and CompoundM.query(rule, "auto_compound") ~= 1 then
                -- 可以合成的材料
                table.insert(tab, {self.heroId, classId});

                self.tab = tab;

                self.classId = classId;
                -- 初始化窗口
                self:initForm();

                -- 重绘
                self:redraw();
            elseif classId == "money" then
                local ownNum = ME.user.dbase:query(classId) or 0;
                if ownNum < requireNum then
                    showMoneyLackConfirm(requireNum);
                end
            elseif classId == ITEM_ID_RELIC then
                local ownNum = ItemM.getAmount(ME.user, classId) or 0;
                if ownNum < requireNum then
                    showScrapLackConfirm(requireNum);
                end
            else
                -- 无法合成的材料

                -- 打开获取途径界面
                self:openAchieve(classId);
            end
        end
    end

    bgImage:addTouchEventListener(onClick);
    itemImg:addTouchEventListener(onClick);
end

-- 注册点击事件
function UIItemCompound:registerTouchEvent()
    -- 注册返回按钮点击事件
    local btnBack = findChildByName(self.node, "BT/btn_back");
    local function onBackClick(sender, eventType)
        if eventType == ccui.TouchEventType.ended then
            if self.waitCommunicate then
                -- 等待通讯不响应
                return;
            end
            -- 关闭当前界面
            AudioM.playFx("button_return");
            local tab = self.tab;

            if #tab > 1 then
                tab[#tab] = nil;
                self.tab = tab;

                -- 如果剩下的是特殊的tab，那么直接退出界面了
                if type(self.tab[#self.tab]) ~= "table" then
                    UIMgr.getCurrentScene():removeFormByName("UIItemCompound");
                    return;
                end

                self.classId = self.tab[#self.tab][2];

                -- 初始化窗口
                self:initForm();

                -- 重绘
                self:redraw();

            else
                -- 刷新下显示
                local uiForm = UIMgr.getCurrentScene():getFormByName("UINewAirShipStrengthen");
                if uiForm then
                    uiForm:redrawAirShipParts();
                end

                UIMgr.getCurrentScene():removeFormByName("UIItemCompound");
            end
        end
    end
    AddBackEventHandler(self, btnBack, onBackClick);

    -- 注册确定按钮点击事件
    local btnOk = findChildByName(self.node, "CT/btn_ok");
    local function onOkClick(sender, eventType)
        if eventType == ccui.TouchEventType.ended then
            if self.waitCommunicate then
                -- 等待通讯不响应
                return;
            end
            AudioM.playFx("button_click");

            if self.type == TYPE_FOOD then
                -- 阶位不足
                local pet = PetM.getMyPet(self.heroId);
                if PetM.canLevelUp(pet) == "rank_limit" then
                    alert(getLocStr("hero_rank_cannot_up"));
                    return;
                end

                -- 如果食物足够，执行喂食（暂时不考虑属性消耗）
                if PetM.isFoodEnough(self.heroId, self.feedId) then
                    -- 直接播放动画
                    local ruleId = CompoundM.getCompoundRule(self.classId);
                    UIMgr.getCurrentScene():removeFormByName("UIMaterialCompound");

                    local uiFoodCompound = UIMaterialCompound.create(ruleId, self.heroId, self.feedId, "food");
                    UIMgr.getCurrentScene():addForm(uiFoodCompound);
                else
                    local ret = PetM.isMaterialEnough(self.heroId, "food", self.feedId);
                    if ret ~= true then
                        if ret == "money_lack" then
                            -- 金币不足
                            alert(getLocStr("compound_pet_food_money_lack"));
                        else
                            -- 食材不足，无法合成
                            alert(getLocStr("compound_pet_food_fail"));
                        end
                        return;
                    end
                    self.waitCommunicate = true;

                    local function delay()
                        if self.waitCommunicate then
                            -- 增加通信中动画
                            showCommunicatingForm();
                        end
                    end
                    performWithDelay(self.node, delay, 0.5);
                end

                -- 合成食物（合成成功后，再自动喂食）
                Operation.cmd_compound_and_feed(self.heroId, self.feedId);
            elseif self.type == TYPE_AIRSHIP_DEVICE then
                -- 强化等级限制
                if not NewAirShipM.canStrengthen(self.heroId, self.feedId) then
                    return;
                end

                -- 如果强化装置足够，开始进行强化
                if NewAirShipM.isDeviceEnough(self.heroId, self.feedId) then
                    -- 直接播放动画
                    local ruleId = CompoundM.getCompoundRule(self.classId);
                    UIMgr.getCurrentScene():removeFormByName("UIMaterialCompound");

                    local uiFoodCompound = UIMaterialCompound.create(ruleId, self.heroId, self.feedId, "device");
                    UIMgr.getCurrentScene():addForm(uiFoodCompound);
                else
                    local ret = NewAirShipM.isMaterialEnough(self.heroId, self.feedId);
                    if ret ~= true then
                        if ret == "money_lack" then
                            -- 金币不足
                            alert(getLocStr("compound_pet_food_money_lack"));
                        else
                            -- 食材不足，无法合成
                            alert(getLocStr("compound_pet_food_fail"));
                        end
                        return;
                    end
                    self.waitCommunicate = true;

                    local function delay()
                        if self.waitCommunicate then
                            -- 增加通信中动画
                            showCommunicatingForm();
                        end
                    end
                    performWithDelay(self.node, delay, 0.5);

                    -- 合成食物（合成成功后，再自动喂食）
                    NewAirShipM.compoundAndStrengthenDevice(self.heroId, self.feedId);
                end
            elseif self.type == TYPE_DEVICE_MATERIAL then
                local ret = NewAirShipM.canMaterialCompound(self.classId);
                if ret ~= true then
                    if ret == "money_lack" then
                        -- 金币不足
                        alert(getLocStr("compound_pet_food_money_lack"));
                    else
                        -- 食材不足，无法合成
                        alert(getLocStr("compound_pet_food_fail"));
                    end
                    return;
                end
                -- 合成装置
                NewAirShipM.compoundMaterial(self.classId);
            elseif self.type == TYPE_EQUIP then
                -- 尚未通关第一小关，暂不能装备(SLIMEC-6479)
                if DungeonAreaM.isDungeonPassed(ME.user, 11) == false then
                    alert(string.format(getLocStr("slime_food_open"), "  " .. DungeonAreaM.query(11, "name") .. "  "));
                    return;
                end

                -- 迷宫暂离时，当前冈布奥是出战冈布奥(不可佩戴专属)（SLIMEC-3367）
                local activeHero = ME.user:getActivePet();

                if DungeonM.isInDungeon() and activeHero.classId == self.heroId then
                    alert(getLocStr("cant_wear_weapon"));
                    return;
                end

                -- 合成装备
                -- 获取物品合成规则
                local rule = CompoundM.getCompoundRule(self.classId);

                local ret = CompoundM.canDoCompound(rule);
                if ret ~= true then
                    if ret == "money_lack" then
                        -- 金币不足
                        alert(getLocStr("compound_pet_food_money_lack"));
                    else
                        -- 食材不足，无法合成
                        alert(getLocStr("compound_pet_food_fail"));
                    end
                    return;
                end

                self.waitCommunicate = true;

                local function delay()
                    if self.waitCommunicate then
                        -- 增加通信中动画
                        showCommunicatingForm();
                    end
                end
                performWithDelay(self.node, delay, 0.5);

                -- 通知服务器 合成装备
                Operation.cmd_do_compound(rule);
            else
                -- 其他类型的物品
                local rule = CompoundM.getCompoundRule(self.classId);
                local ret = CompoundM.canDoCompound(rule);
                if ret ~= true then
                    if ret == "money_lack" then
                        -- 金币不足
                        alert(getLocStr("compound_pet_food_money_lack"));
                    else
                        -- 食材不足，无法合成
                        alert(getLocStr("compound_pet_food_fail"));
                    end
                    return;
                end

                -- 考虑可能在迷宫中
                self:tryToCompound(rule, 1);
            end
        end
    end
    btnOk:addTouchEventListener(onOkClick);

    -- 合成 按钮
    local btnCompound = findChildByName(self.node, "CT/btn_compound");
    btnCompound:addTouchEventListener(onOkClick);

    -- 合成10次 按钮
    local btnCompoundTen = findChildByName(self.node, "CT/btn_compound_ten");
    local function multiCompoundItem()
        local maxNum = btnCompoundTen.maxNum or 1;
        local rule = CompoundM.getCompoundRule(self.classId);
        local ret = CompoundM.canDoCompound(rule, maxNum);
        if ret ~= true then
            if ret == "money_lack" then
                -- 金币不足
                alert(getLocStr("compound_pet_food_money_lack"));
            else
                -- 食材不足，无法合成
                alert(getLocStr("compound_pet_food_fail"));
            end
            return;
        end

        -- 合成食材
        Operation.cmd_do_compound(rule, maxNum);
    end

    local function onCompoundTenClick(sender, eventType)
        if eventType == ccui.TouchEventType.ended then
            AudioM.playFx("button_click");

            performWithDelay(self, multiCompoundItem, 0.1);
        end
    end
    btnCompoundTen:addTouchEventListener(onCompoundTenClick);

    -- 获取途径 按钮
    local btnCompound = findChildByName(self.node, "CT/btn_achieve");
    local function onAchieveClick(sender, eventType)
        if eventType == ccui.TouchEventType.ended then
            AudioM.playFx("button_click");

            -- 打开获取途径界面
            self:openAchieve(self.classId);
        end
    end
    btnCompound:addTouchEventListener(onAchieveClick);

    local buyMaterialImg = findChildByName(self.node, "CT/buy_material");
    local function onBuyMaterial(sender, eventType)
        if eventType == ccui.TouchEventType.began then
           buyMaterialImg:runAction(cc.ScaleTo:create(0.1, 0.97));
        elseif eventType == ccui.TouchEventType.canceled then
            buyMaterialImg:runAction(cc.ScaleTo:create(0.1, 1));
        elseif eventType == ccui.TouchEventType.ended then
            buyMaterialImg:runAction(cc.ScaleTo:create(0.1, 1));
            AudioM.playFx("button_click");
            self:showBuyMaterial();
        end
    end

    buyMaterialImg:addTouchEventListener(onBuyMaterial);
end

-- 注册事件处理回调函数
function UIItemCompound:registerEventCallback()
    -- 关注英雄升级的事件（喂食成功）
    EventMgr.register("UIItemCompound", event.PET_LEVEL_UP, function(args)
        EventMgr.fire(event.FEED_PET_SHOW_CHANGE, self.heroId);

        UIMgr.getCurrentScene():removeFormByName("UIItemCompound");
    end);

    -- 关注合成成功的事件
    EventMgr.register("UIItemCompound", event.DO_COMPOUND, function(args)
        self:whenDoCompound(args);
    end);

    -- 注册获得焦点的回调
    EventMgr.register("UIItemCompound", event.FOCUS_CHANGED, function(para)
        if para["get"] == "UIItemCompound" then
            if self.type == TYPE_AIRSHIP_DEVICE or self.type == TYPE_DEVICE_MATERIAL or self:getTopMenueNoChange() then
                UIMgr:getCurrentScene().topMenu:show(TOPMENU_FRAME_MONEY, TOPMENU_FRAME_RUINS_SCRAP);
            else
                UIMgr:getCurrentScene().topMenu:show(TOPMENU_FRAME_MONEY, TOPMENU_FRAME_GEM);
            end
        end
    end);

    -- 注册找零后回调
    EventMgr.register("UIItemCompound", event.GET_BUY_MATERIAL_CHANGE, function(args)
        local function callback()
             showBonusNotifyForm(getLocStr("title_money_change"), args.bonusList);
        end

        local msgList = {getLocStr("give_back_change"),};
        local UIHeroSpeak = UIHeroSpeak.create(self, 18, msgList, "B_FLY_IN", "B_FLY_OUT", nil, callback);
        UIMgr.getCurrentScene():addForm(UIHeroSpeak);
    end);

    -- 界面析构后，需要清理下
    self:registerScriptHandler(function(ev)
        if ev == "exit" then
            cclog("UIItemCompound 界面析构清理");

            EventMgr.removeAll("UIItemCompound");
            local uiSlimeFoodInfo = UIMgr.getCurrentScene():getFormByName("UISlimeFoodInfo");
            local uiNewAirShipStrengthen = UIMgr.getCurrentScene():getFormByName("UINewAirShipStrengthen");
            if uiSlimeFoodInfo or uiNewAirShipStrengthen then
                local topMenu = UIMgr.getCurrentScene().topMenu;
                if topMenu then
                    topMenu:setVisible(false);
                end

                if uiSlimeFoodInfo then
                    uiSlimeFoodInfo:tryRedraw();
                end
            end

        elseif ev == "enter" then
            UIMgr.getCurrentScene().topMenu:setVisible(true);
        end

    end);

    -- 注册购买商品的事件回调(可能会直接购买碎片)
    EventMgr.register("UIItemCompound", event.DIRECT_BUY_GOODS, function(args)
        if self.type ~= TYPE_AIRSHIP_DEVICE then
            alertBuyGoodsTip(args.bonus);
        end
        self:redraw();
    end);
end

-- 保持不变的参数
function UIItemCompound:setTopMenueNoChange(noChange)
    self.noChange = noChange;
end

-- 获取保持不变的参数
function UIItemCompound:getTopMenueNoChange()
    return self.noChange;
end

-- 是否是食物合成
function UIItemCompound:isFoodCompound(ruleId)
    local product = CompoundM.query(ruleId, "product");
    if not product then
        -- 获取不到产物
        return false;
    end

    local productInfo = product[1];

    if productInfo[1] ~= 1 then
        -- 不是物品合成
        return false;
    end

    local classId = productInfo[2];
    local itemType = ItemM.query(classId, "type");
    if ITEM_TYPE_FOOD ~= itemType then
        -- 不是食物
        return false;
    end

    return true;
end

-- 合成成功的事件
function UIItemCompound:whenDoCompound(args)
    local ruleId = args.ruleId;
    local count = args.count;
    local product = CompoundM.query(ruleId, "product");

    -- 标记不需要
    self.waitCommunicate = false;

    -- 关闭通信中界面
    closeCommunicatingForm();

    if not product then
        -- 获取不到产物
        return;
    end

    local productInfo = product[1];

    if productInfo[1] ~= 1 then
        -- 不是物品合成
        return;
    end

    local classId = productInfo[2];
    local itemType = ItemM.query(classId, "type");

    if ITEM_TYPE_FOOD == itemType then
        -- 播放食物合成动画
        UIMgr.getCurrentScene():removeFormByName("UIMaterialCompound");

        local uiFoodCompound = UIMaterialCompound.create(ruleId, self.heroId, self.feedId, "food");
        UIMgr.getCurrentScene():addForm(uiFoodCompound);
    elseif ITEM_TYPE_AIRSHIP_DEVICE == itemType then
        -- 播放食物合成动画
        UIMgr.getCurrentScene():removeFormByName("UIMaterialCompound");

        local uiFoodCompound = UIMaterialCompound.create(ruleId, self.heroId, self.feedId, "device");
        UIMgr.getCurrentScene():addForm(uiFoodCompound);
    elseif ITEM_TYPE_MATERIAL == itemType then
        -- 重绘
        self:redraw();

        local itemNode = findChildByName(self.node, "CT/item/effectNode");

        itemNode:removeAllChildren();

        if count > 1 then
            playEffect(itemNode, 1231, 30, -55,  nil, 0.82);
        else
            playEffect(itemNode, 1180, 30, -55,  nil, 0.82);
        end
    elseif ITEM_TYPE_DEVICE_MATERIAL == itemType or
        self.type == TYPE_AWAKE_PEARL then
        -- 重绘
        self:redraw();

        local itemNode = findChildByName(self.node, "CT/item/effectNode");

        itemNode:removeAllChildren();

        if count > 1 then
            playEffect(itemNode, 1231, 30, -55,  nil, 0.82);
        else
            playEffect(itemNode, 1180, 30, -55,  nil, 0.82);
        end
    elseif ITEM_TYPE_WEAPON == itemType then
        local function callback()
            -- 请求装备
            local pet = PetM.getMyPet(self.heroId);
            Operation.cmd_hero_equip(pet, classId);

            -- 关闭当前界面
            UIMgr.getCurrentScene():removeFormByName("UIItemCompound");
        end

        performWithDelay(self, callback, 0.1);
    else
        -- 普通物品合成
        -- 重绘
        self:redraw();

        -- 音效
        AudioM.playFx("admix_food");

        UIMgr.getCurrentScene():removeFormByName("UIMaterialCompound");
        local uiFoodCompound = UIMaterialCompound.create(ruleId, self.heroId);
        UIMgr.getCurrentScene():addForm(uiFoodCompound);

        -- 如果无法再合成，则关闭合成界面
        local rule = CompoundM.getCompoundRule(self.classId);
        if true ~= CompoundM.canDoCompound(rule) then
            closeFormByName("UIItemCompound");
        end
    end
end

-- 打开获取途径界面
function UIItemCompound:openAchieve(classId)
    -- 先判断有没有获取途径
    local pathList = GainItemPathM.query(classId, "paths");

    if pathList == nil then
        return;
    end

    -- 打开界面
    -- 传入classId和self.tab
    if UIMgr:getCurrentScene():isOpen("UIGainItemPath") then
        UIMgr:getCurrentScene():removeForm("UIGainItemPath");
    end

    local uiItemPath = UIGainItemPath.create(classId, self.tab, "air_ships");
    UIMgr.getCurrentScene():addForm(uiItemPath);
end

-- 记录合成序列
function UIItemCompound:tryToCompound(ruleId, num)
    local classId = self.classId;
    if DungeonM.getState() == DUNGEON_GAMING then
        return DungeonActionM.go("do_compound", num, classId);
    end

    if not CompoundM.doCompound(ruleId, "compound", num) then
        return false;
    end
    if not self.compoundList then
        self.compoundList = {};
    end

    local compoundNum = num or 1;
    if #self.compoundList > 0 then
        if self.compoundList[1] ~= ruleId then
            self:clearCompoundList();
        else
            compoundNum = compoundNum + self.compoundList[2];
        end
    end

    self.compoundList = {ruleId, compoundNum};

    -- 不要等到之后再同步！！！
    -- 因为如果在此界面等待一段时间之后，材料数量会被服务器的工坊给同步掉，导致两边不一致
    self:clearCompoundList();
    return true, true;
end

-- 清空合成序列
function UIItemCompound:clearCompoundList()
    if not self.compoundList then
        self.compoundList = {};
    end

    if #self.compoundList > 0 then
        Operation.cmd_do_compound(self.compoundList[1], self.compoundList[2], true);
    end

    self.compoundList = {};
end

-- 检测是否需要清空序列
function UIItemCompound:checkToClear()
    if not self.compoundList then
        self.compoundList = {};
    end

    if #self.compoundList > 0 then
        local rule = CompoundM.getCompoundRule(self.classId);

        if rule ~= self.compoundList[1] then
            self:clearCompoundList();
        end
    end
end

-- 注册标签按钮回调
function UIItemCompound:itemPathCallback(index)

    local touchTab = self.tab[index];

    self.heroId = touchTab[1];
    self.classId = touchTab[2];

    local tab = {}

    for i = 1, index do
        table.insert(tab, self.tab[i]);
    end
    self.tab = tab;

    -- 初始化窗口
    self:initForm();

    -- 重绘
    self:redraw();
end

-- 显示一键购买
function UIItemCompound:showBuyMaterial()
    if UIMgr:getCurrentScene():isOpen("UIBuyMaterial") then
        UIMgr:getCurrentScene():removeForm("UIBuyMaterial");
    end

    local uiForm = UIBuyMaterial.create(self.classId, self.materialList);
    UIMgr.getCurrentScene():addForm(uiForm);
end

-- 获取商城冈布奥碎片的id
function UIItemCompound:getScrapIds()
    local ids = {};
    -- 需要检查活动碎片
    local finalList = MarketM.getSellScrapList(true);
    if #finalList == 0 then
        return ids;
    end

    for i = 1, #finalList do
        local info = finalList[i].bonus;
        table.insert(ids, info[1][2]);
    end

    return ids;
end

-- 判断可以直接购买
function UIItemCompound:isCanBuy(activityId)
    if tonumber(activityId) > 0
        and ActivityDungeonM.getCurrentActivityId() ~= activityId then
        -- 不是活动期间
        return false;
    end

    local groupId = ItemM.query(self.classId, "group");

    if groupId ~= 13 then
        return true;
    end

    local ids = self:getScrapIds();
    local materialId;
    if type(self.materialList[1]) == "table" then
        materialId = self.materialList[1].classId;
    else
        return false;
    end

    if table.indexOf(ids, materialId) ~= -1 then
        return true;
    end

    return false;
end
